﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization;
using SAPbouiCOM;

namespace SapFramework.Interface.Events.EventCollections
{
    public class FiltersDictionary : Dictionary<SAPbouiCOM.BoEventTypes, HashSet<string> >
    {
        #region Construtores - Passados para internal para que não se possam criar instâncias desta classe fora desta DLL (em especial, da classe EventListener)

        /// <summary>
        /// Initializes a new instance of the <see cref="T:System.Collections.Generic.Dictionary`2"/> class that is empty, has the default initial capacity, and uses the default equality comparer for the key type.
        /// </summary>
        internal FiltersDictionary() {}

        /// <summary>
        /// Initializes a new instance of the <see cref="T:System.Collections.Generic.Dictionary`2"/> class that is empty, has the specified initial capacity, and uses the default equality comparer for the key type.
        /// </summary>
        /// <param name="capacity">The initial number of elements that the <see cref="T:System.Collections.Generic.Dictionary`2"/> can contain.</param><exception cref="T:System.ArgumentOutOfRangeException"><paramref name="capacity"/> is less than 0.</exception>
        internal FiltersDictionary( int capacity ) : base( capacity ) {}

        /// <summary>
        /// Initializes a new instance of the <see cref="T:System.Collections.Generic.Dictionary`2"/> class that is empty, has the default initial capacity, and uses the specified <see cref="T:System.Collections.Generic.IEqualityComparer`1"/>.
        /// </summary>
        /// <param name="comparer">The <see cref="T:System.Collections.Generic.IEqualityComparer`1"/> implementation to use when comparing keys, or null to use the default <see cref="T:System.Collections.Generic.EqualityComparer`1"/> for the type of the key.</param>
        internal FiltersDictionary( IEqualityComparer<BoEventTypes> comparer ) : base( comparer ) {}

        /// <summary>
        /// Initializes a new instance of the <see cref="T:System.Collections.Generic.Dictionary`2"/> class that is empty, has the specified initial capacity, and uses the specified <see cref="T:System.Collections.Generic.IEqualityComparer`1"/>.
        /// </summary>
        /// <param name="capacity">The initial number of elements that the <see cref="T:System.Collections.Generic.Dictionary`2"/> can contain.</param><param name="comparer">The <see cref="T:System.Collections.Generic.IEqualityComparer`1"/> implementation to use when comparing keys, or null to use the default <see cref="T:System.Collections.Generic.EqualityComparer`1"/> for the type of the key.</param><exception cref="T:System.ArgumentOutOfRangeException"><paramref name="capacity"/> is less than 0.</exception>
        internal FiltersDictionary( int capacity, IEqualityComparer<BoEventTypes> comparer ) : base( capacity, comparer ) {}

        /// <summary>
        /// Initializes a new instance of the <see cref="T:System.Collections.Generic.Dictionary`2"/> class that contains elements copied from the specified <see cref="T:System.Collections.Generic.IDictionary`2"/> and uses the default equality comparer for the key type.
        /// </summary>
        /// <param name="dictionary">The <see cref="T:System.Collections.Generic.IDictionary`2"/> whose elements are copied to the new <see cref="T:System.Collections.Generic.Dictionary`2"/>.</param><exception cref="T:System.ArgumentNullException"><paramref name="dictionary"/> is null.</exception><exception cref="T:System.ArgumentException"><paramref name="dictionary"/> contains one or more duplicate keys.</exception>
        internal FiltersDictionary( IDictionary<BoEventTypes, HashSet<string>> dictionary ) : base( dictionary ) {}

        /// <summary>
        /// Initializes a new instance of the <see cref="T:System.Collections.Generic.Dictionary`2"/> class that contains elements copied from the specified <see cref="T:System.Collections.Generic.IDictionary`2"/> and uses the specified <see cref="T:System.Collections.Generic.IEqualityComparer`1"/>.
        /// </summary>
        /// <param name="dictionary">The <see cref="T:System.Collections.Generic.IDictionary`2"/> whose elements are copied to the new <see cref="T:System.Collections.Generic.Dictionary`2"/>.</param><param name="comparer">The <see cref="T:System.Collections.Generic.IEqualityComparer`1"/> implementation to use when comparing keys, or null to use the default <see cref="T:System.Collections.Generic.EqualityComparer`1"/> for the type of the key.</param><exception cref="T:System.ArgumentNullException"><paramref name="dictionary"/> is null.</exception><exception cref="T:System.ArgumentException"><paramref name="dictionary"/> contains one or more duplicate keys.</exception>
        internal FiltersDictionary( IDictionary<BoEventTypes, HashSet<string>> dictionary, IEqualityComparer<BoEventTypes> comparer ) : base( dictionary, comparer ) {}

        /// <summary>
        /// Initializes a new instance of the <see cref="T:System.Collections.Generic.Dictionary`2"/> class with serialized data.
        /// </summary>
        /// <param name="info">A <see cref="T:System.Runtime.Serialization.SerializationInfo"/> object containing the information required to serialize the <see cref="T:System.Collections.Generic.Dictionary`2"/>.</param><param name="context">A <see cref="T:System.Runtime.Serialization.StreamingContext"/> structure containing the source and destination of the serialized stream associated with the <see cref="T:System.Collections.Generic.Dictionary`2"/>.</param>
        internal FiltersDictionary( SerializationInfo info, StreamingContext context ) : base( info, context ) { }

        #endregion

        /// <summary>
        /// Indexador para facilitar acesso 
        /// </summary>
        /// <param name="aEventType">Tipo do evento capturado do SAP Business One.</param>
        /// <returns></returns>
        public new HashSet<string> this[SAPbouiCOM.BoEventTypes aEventType]
        {
            get
            {
                if ( !ContainsKey( aEventType ) )
                {
                    base.Add( aEventType, new HashSet<string>() );
                }
                
                return base[aEventType];
            }
            private set { base[aEventType] = value; }
        }

        public SAPbouiCOM.EventFilters BuildSboEventFilters()
        {
            #region Garante que, para cada formulário, os eventos de et_FORM_LOAD e et_FORM_CLOSE sejam mapeados

            IEnumerable<string> lEnmFormTypes =
                from
                    sHashSet in Values
                from
                    sFormType in sHashSet
                select
                    sFormType;

            HashSet<string> lSetFormTypes = new HashSet<string>( lEnmFormTypes );

            this[BoEventTypes.et_FORM_LOAD] = lSetFormTypes;
            this[BoEventTypes.et_FORM_CLOSE] = lSetFormTypes;

            #endregion

            EventFilters lEventFilters = new EventFilters();

            foreach ( BoEventTypes lEventType in Keys )
            {
                EventFilter lEventFilter = lEventFilters.Add( lEventType );
                
                foreach ( string lFormType in this[lEventType] )
                {
                    lEventFilter.AddEx( lFormType );
                } 
            }

            return lEventFilters;
        }
    }
}